package com.logistics.modules.warehouseManagement.service.impl;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.result.ExcelImportResult;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.NumberUtil;
import com.logistics.modules.transportationManagement.dao.CargotypeDao;
import com.logistics.modules.transportationManagement.entity.CargotypeEntity;
import com.logistics.modules.warehouseManagement.dao.RepositoryDao;
import com.logistics.modules.warehouseManagement.dao.SeatDao;
import com.logistics.modules.warehouseManagement.entity.RepositoryEntity;
import com.logistics.modules.warehouseManagement.entity.SeatEntity;
import com.logistics.modules.warehouseManagement.from.InitRepository;
import com.logistics.modules.warehouseManagement.from.InitializationRules;
import com.logistics.modules.warehouseManagement.service.InitRepositoryService;
import com.logistics.modules.warehouseManagement.service.SeatService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.List;

/**
 * 初始化库服务impl
 *
 * @author 水穷处云起时
 * @date 2022/05/09
 */
@Service
public class InitRepositoryServiceImpl implements InitRepositoryService {


    private RepositoryDao repositoryDao;
    private SeatDao seatDao;
    private SeatService seatService;
    private CargotypeDao cargotypeDao;

    public InitRepositoryServiceImpl() {}

    @Autowired
    public InitRepositoryServiceImpl(RepositoryDao repositoryDao, SeatDao seatDao, SeatService seatService, CargotypeDao cargotypeDao) {
        this.repositoryDao = repositoryDao;
        this.seatDao = seatDao;
        this.seatService = seatService;
        this.cargotypeDao = cargotypeDao;
    }

    /**
     * 查询所有
     *
     * @return {@link List}<{@link InitRepository}>
     */
    @Override
    public List<InitRepository> queryAll() {
        // 要返回的数据
        ArrayList<InitRepository> initRepositories = new ArrayList<>();
        // 把数据库的数据封装成initRepository集合
        // 去数据库拿到所有的数据集合
        List<RepositoryEntity> repositoryEntities = repositoryDao.selectList(null);
        // 循环遍历
        repositoryEntities.forEach(repository -> {
            // 展示的对象
            InitRepository initRepository = new InitRepository();
            // 根据id查它对应的席位表
            List<SeatEntity> seatEntities = seatDao.selectAllByRepositoryId(repository.getId());
            if (seatEntities != null && seatEntities.size() > 0) {
                // 统计席位集合中使用的席位
                Integer percentage = countSeatsUsedInASeatSet(seatEntities,repository);
                // 设置百分比
                initRepository.setPercentage(percentage);
                initRepository.setWhetherToInitialize(true);
            } else {
                // 该仓库未进行初始化
                initRepository.setPercentage(0);
                initRepository.setWhetherToInitialize(false);
            }
            initRepository.setRepositoryId(repository.getId());
            initRepository.setRepositoryName(repository.getStoreName());
            initRepository.setTotalSeats(seatEntities.size());
            // 设置总容量
            initRepository.setTotalCapacity(repository.getStoreVolume());
            // add
            initRepositories.add(initRepository);
        });


        return initRepositories;
    }

    /**
     * 初始化仓库
     *  根据初始化规则生成席位
     * @param initializationRules 初始化规则
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void initializeWarehouse(InitializationRules initializationRules) {
        // 1.读取要生成的规则
        Integer seatRules = initializationRules.getSeatRules();
        // 查询仓库实体类
        RepositoryEntity repositoryEntity = repositoryDao.selectOneById(initializationRules.getRepositoryId());
        // 规则
        String rule = null;
        // 1.1根据用户选择生成的规则填充对应的内容
        switch (seatRules) {
            case 0:
                rule = null;
                break;
            case 1:
                rule = repositoryEntity.getStoreName();
                break;
            case 2:
                rule = initializationRules.getPrefix();
                break;
        }
        // 2.根据要生成的规则去生成席位
        List<SeatEntity> result = generateSeats(rule,initializationRules,repositoryEntity);
        // 3.通过循环把生成的对象批量保存
        boolean res = seatService.saveBatch(result);

        if (!res) {
            throw new RuntimeException("批量生成席位失败!");
        }

    }

    /**
     * 根据导入进来的excel实现初始化
     *
     * @param file 文件
     * @param id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void initializeWarehouseByExport(MultipartFile file, Integer id) {
        // 席位的排序
        int order = 0;
        // 席位的总容量
        int totalCapacity = 0;

        ImportParams params = new ImportParams();
        params.setTitleRows(1);
        params.setHeadRows(1);
        params.setNeedSave(true);

        ExcelImportResult<SeatEntity> result = null;
        try {
            result = ExcelImportUtil.importExcelMore(file.getInputStream(), SeatEntity.class, params);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("生成席位失败!");
        }

        //使用api获取到的List数据
        List<SeatEntity> seates = result.getList();
        List<SeatEntity> seatSave = new ArrayList<>();
        // 开始批量保存
        for (SeatEntity seat : seates) {
            // 查询货物分类名称对应的类型
            Integer integer = cargotypeDao.selectOneByCargoTypeName(seat.getCargoType().getCargoTypeName());
            if (integer == null || integer < 1) {
                throw new RuntimeException("数据校验失败! 没有该货物类型! 错误在正文第" + (order + 1) + "行");
            }
            if (!checkSeat(seat)) {
                throw new RuntimeException("数据校验失败! 生成失败! 错误在正文第" + (order + 1) + "行");
            }
            // 累计席位总容量
            totalCapacity+=seat.getSeatVolume();
            seat.setSeatStatus(0);
            seat.setRepositoryId(id);
            seat.setSeatOrder(order);
            seat.setCargoTypeId(integer);
            seatSave.add(seat);
            // ++
            order++;
        }
        // 效验总容量
        if (!checkSeatTotalCapacity(totalCapacity, id)) {
            throw new RuntimeException("所有席位总容量超过仓库总容量大小! 生成失败!");
        }
        // 批量保存到数据库
        this.seatService.saveBatch(seatSave);
    }

    /**
     * 检查座椅总容量
     *
     * @param totalCapacity 总容量
     * @param id            id
     * @return boolean
     */
    private boolean checkSeatTotalCapacity(int totalCapacity, Integer id) {
        RepositoryEntity repositoryEntity = this.repositoryDao.selectOneById(id);
        return repositoryEntity.getStoreVolume() >= (totalCapacity - 5);
    }

    /**
     * 进行数据校验
     *
     * @param seat 座位
     * @return boolean
     */
    private boolean checkSeat(SeatEntity seat) {
        if (seat.getSeatVolume() == null || seat.getSeatVolume() < 0) {
            return false;
        }
        if (seat.getSeatName() == null || seat.getSeatName() == "") {
            return false;
        }
        if (seat.getCargoType().getCargoTypeName() == null || seat.getCargoType().getCargoTypeName() == "") {
            return false;
        }
        return true;
    }

    /**
     * 生成座位
     *
     * @param rule                规则
     * @param initializationRules 初始化规则
     * @return {@link List<SeatDao>}
     */
    private List<SeatEntity> generateSeats(String rule, InitializationRules initializationRules, RepositoryEntity repositoryEntity) {
        // 要返回的结果
        ArrayList<SeatEntity> seats = new ArrayList<>();
        // 去数据库中拿到货物分类的数据
        List<CargotypeEntity> cargotypeEntities = cargotypeDao.selectList(null);
        // 货物分类的所有数据
        List<Integer> cargoTypeIds = new ArrayList<>();
        for (CargotypeEntity cargotypeEntity : cargotypeEntities) {
            cargoTypeIds.add(cargotypeEntity.getId());
        }
        // 默认生成规则
        for (int i = 0; i < initializationRules.getNumberOfSeats(); i++) {
            SeatEntity seatEntity = new SeatEntity();
            // 设置名称
            if (rule == null) {
                seatEntity.setSeatName(i + "");
            } else {
                seatEntity.setSeatName(rule + "-" + i);
            }
            // 设置仓库id
            seatEntity.setRepositoryId(repositoryEntity.getId());
            // 设置席位大小
            seatEntity.setSeatVolume(initializationRules.getSeatSize());
            // 设置排序字段
            seatEntity.setSeatOrder(i);
            // 设置状态默认是空闲
            seatEntity.setSeatStatus(0);
            // 设置货物分类信息
            seatEntity.setCargoTypeId(cargoTypeIds.get(i % cargoTypeIds.size()));
            // 添加到集合中
            seats.add(seatEntity);
        }


        return seats;
    }

    /**
     * 统计席位集合中使用的席位
     *
     * @param seatEntities 座位实体
     * @param repository   存储库
     * @return {@link Integer} 是一个百分比
     */
    protected Integer countSeatsUsedInASeatSet(List<SeatEntity> seatEntities, RepositoryEntity repository) {
        // 已使用的容量
        Double usedCapacity = 0.0;
        // 总容量
        Double totalCapacity = (double)repository.getStoreVolume();
        // 百分比
        Integer percentage = 0;
        // 统计已使用的容量
        for (SeatEntity seatEntity : seatEntities) {
            // 席位在已使用中则统计容量
            if (seatEntity.getSeatStatus() == 1) {
                usedCapacity = usedCapacity + seatEntity.getSeatVolume();
            }
        }
        // 计算总容量 　数量÷总数×100=百分比
        percentage = Convert.toInt(NumberUtil.mul(NumberUtil.div(usedCapacity, totalCapacity), 100));
        // 返回
        return percentage;
    }



}
